1. Field of the Invention
Systems and methods consistent with the present invention relate to an object request broker for event notification. More particularly, the present invention is consistent with providing automatic generation of code with the generated code thereafter being compilable so as to provide multiple remote clients in distributed computing access to server object events.
2. Description of the Related Art
The widespread deployment of computer networks has significantly expanded the usefulness of personal computers (PC's). Explosive growth in the world-wide web of the Internet has been followed by large database applications once cloistered on internal mainframe computers migrating to smaller, less-expensive server workstations and PCs. Distributed computing has reduced the computing burden on central servers by partitioning software applications across server and client machines. In distributed computing, the machines on which the client and server programs execute are different and are connected through a network such as the Internet, or a corporate Intranet or Extranet. Both the client and server machines must use a standard communications protocol, in order to communicate with each other.
One conventional protocol used with client/server computing is the Remote Procedure Call (“RPC”). With RPC, a programmer codes a module (e.g., procedure call) but only a “stub” for that module is generated during program compilation. A “stub” is a special construct enabling the program to successfully compile without resolving the address of the referenced procedure. If the procedure is actually called during runtime, a request to execute the code will be forwarded to a server where the module is available. That server will perform the function of the procedure, and return the results transparently to the client.
More sophisticated distributed-computing models and applications use an object-oriented approach with larger applications being divided into small containers or “objects” of program code and data. The program objects are distributed to both the server and the clients, with the details of network communication hidden from objects through the use of proxy and stub objects, which transfer information over the network. Object Management Group's Common Object Request Broker Architecture (CORBA) and Microsoft's Distributed Component Object Model (DCOM) are two competing standards for distributed computing.
CORBA, for example, is comprised of objects, where for each object type, there is an interface and an implementation code for accessing a particular object type. As shown in FIG. 1, an interface contains a list of attributes 1, 2 . . . n (e.g., name, social security number, date of birth) and a list of methods 1, 2 . . . n (e.g., get_social_security( ); change_social_security( ); add_social_security( )) to be invoked for that particular object type. An interface is defined in an Interface Definition Language (IDL), which provides for encapsulation, polymorphism, and inheritance. The interface is the syntax part of the contract that the server object offers to the clients that invoke it. Any client that wants to invoke an operation on the object must use this IDL interface to specify the operation it wants to perform, and to marshal the arguments that it sends. When the invocation reaches the target object, the same interface definition is used there to unmarshal the arguments so that the object can perform the requested operation with them. The interface definition is then used to marshal the results for their trip back, and to unmarshal them when they reach their destination.
An IDL CORBA tool, as shown in FIG. 1 uses this IDL file to create stubs and skeletons, which serve as proxies for clients and servers, respectively. The IDL is independent of programming language and maps to all of the popular progranming languages. Because IDL defines interfaces so strictly, the stub on the client side has no trouble meshing perfectly with the skeleton on the server side, even if the two are compiled into different programming languages, or even running on different server platforms. For example, object implementations 1, 2 . . . n are located separately, as shown in FIG. 1 (e.g. on a remote servers) from the interfaces.
Sometimes to facilitate development of distributed computing, code generators are used. For example, U.S. Pat. No. 6,199,195 to Goodwin et al. teaches a code generator, which is a model driven application that reads the object elements from a schema server which makes available meta information defining a particular data system or database and applies a set of known service templates for a given framework to an object's elements to produce a set of source code. This code generator can generate code in different languages (e.g. C++, Java) based on user preferences and selection. The code generator also generates CORBA ORB services for specific operations which will replace client stubs. This reference is incorporated herein by reference for its helpful background information.
An object request broker (ORB) provides a mechanism for communicating client requests to the target object implementation, as shown in FIG. 1. The ORB takes care of all of the details involved in routing a request from client to object, and routing the response to its destination. The ORB finds the object implementation and delivers it to a client; thus making the process transparent to the client. Clients use the object references as shown in FIG. 1, e.g. person.get_social_security(“John Smith”), to direct their invocations, identifying to the ORB the exact instance they want to invoke. Passing through the stub on the client side, the invocation continues through the ORB. If the ORB identifies that the object implementation is on a remote server, then ORB routes the request over a standard protocol, e.g., IIOP (Internet Interoperable ORB Protocol), GIOP (General Interoperable ORB Protocol, implemented over TCP), to the ORB of that remote object. The ORB of the remote object implementation passes the request to the skeleton and the skeleton on the implementation side, gets to the object where it is executed. This ORB creates client transparency.
In general, CORBA uses a pull based object distribution to fetch the attributes via their interfaces. That is, the request always originates at the client. However, push-based event notification is also available but only for generic/standard interfaces (e.g. interface for a “string” type) or interfaces of type any.
CORBA Event Model
Events are produced by suppliers and consumed by consumers. Suppliers and consumers are completely decoupled: a supplier has no knowledge of the number of consumers or their identities, and consumers have no knowledge of which supplier generated a given event.
In order to support this model, the CORBA Event Service introduces to CORBA a new architectural element, called an event channel. As shown in FIG. 2, an event channel mediates the transfer of events between the suppliers and consumers as follows:                1. The event channel allows consumers to register interest in events, and stores this registration information at step 201.        2. As an event occurs, the supplier sends event notification to the channel at step 202.        3. The channel accepts incoming events from suppliers at step 203.        4. The channel forwards supplier-generated events to registered consumers at step 204.        
Suppliers and consumers connect to the event channel and not directly to each other. From a supplier's perspective, the event channel appears as a single consumer; from a consumer's perspective, the event channel appears as a single supplier. In this way, the event channel decouples suppliers and consumers.
There are two types of event suppliers: Publishers and Emitters.
Event Source: Publisher
An event originates at an event publisher and is transferred to any number of event consumers. A publisher is guaranteed to be the only source publishing events to that channel.
Event Source: Emitter
An event originates at the event emitter and is transferred to a single consumer. Only one consumer can subscribe to receive events from the emitter. However, multiple emitters can use the same event channel simultaneously. Event communication can take one of two forms, typed or untyped.
Untyped Events
In untyped event communication, an event is propagated by a series of generic push( ) or pull( ) operation calls. The push( ) operation takes a single parameter which stores the event data. The event data parameter is of type any, which allows any IDL defined data type to be passed between suppliers and consumers. The pull( ) operation has no parameters but transmits event data in its return value, which is also of type any. Clearly, in both cases, push( ) or pull( ), the supplier and consumer applications must agree about the contents of the any parameter and return a value if this data is to be useful.
Typed Events
In typed event communication, a programmer defines application-specific IDL interfaces through which events are propagated. Rather than using push( ) and pull( ) operations and transmitting data using a type any, a programmer defines an interface that suppliers and consumers use for the purpose of event communication. The operations defined on the interface may contain parameters defined in any suitable IDL data type. In the Push model, event communication is initiated simply by invoking operations defined on this interface. The Pull model is more complex because event communication is initiated by invoking operations on an interface that is specially constructed from the application-specific interface that the programmer defines. Event communication is initiated by invoking operations on the constructed interface.
The form that event communication takes is independent of the method of initiating event transfer. As a consequence, both the Push model and the Pull model can be used to transmit typed events or untyped events. However, CORBA event notification requires the data being sent to be generalized into an encapsulating mechanism (CORBA::any). Object Management Group (OMG) could not have designed a custom, type-safe interface because they cannot anticipate all data types.
For example, consider the following. The user passes a user-defined (custom) structure that contains two fields: a string and an integer. For the purpose of marshalling this value across the network, the event producer should cast this type to type any. Then, the data is being sent over the network to a consumer and the receiving side performs type cast to supposedly original type. However, if the programmer made a mistake and on the client side the data is being cast from type any to a type different than the original type (e.g. double instead of the original structure, which has a string and an integer) it will cause a run-time error. There is no way for this kind of mistake to be detected at compilation-time. CORBA will only detect these mistakes at run-time.
A Distributed Component Object Model is very similar to CORBA. The COM run-time provides object-oriented services to clients and components and uses RPC and the security provider to generate standard network packets that conform to the DCOM wire-protocol standard. However, it too only provides push-based event notification for generic interfaces. In short, accounting for user-defined (non-generic) interfaces has been a challenge in today's technology.
Various techniques have been developed for a Distributed System in attempts to account for heterogeneous software. For example, in U.S. Pat. No. 6,085,030 to Whitehead, a component of server architecture is provided which allows for a distributed interaction between a client and heterogeneous software by registering and locating the components and services in an object neutral global component registry. Similarly, U.S. patent application Ser. No. 09/841,847 to Killian et al. published on Feb. 14, 2002, shows a client-server system including a method using CORBA to register the association between the interface name and the path name of the server executable in the implementation repository, after compilation but before execution. The IDL compiler also generates type information for each method in an interface and stores it in the interface repository. The client can query the interface repository to get runtime information about a particular interface and then use that to create and invoke a method on the object dynamically through the dynamic invocation interface. For another technique using CORBA to allow intelligent components to discover each other in distributed computing, see U.S. patent application Ser. No. 09/816,282 to Ben-Shachar et al. published on Jul. 26, 2001. All of the above mentioned references are incorporated herein by reference for their helpful background information.
However, these techniques just like the pull-based approaches provided by CORBA and DCOM have low scalability. These systems cannot scale to a significant number of clients; they are limited to point-to-point protocols. Using a push-based approach allows communication using one-to-many protocols. Emerging standards for scalable multicast (SRM) can be employed to provide Internet-scale numbers of clients. On the other hand, although the push approach is available, it is implemented only with respect to generic, standard interfaces. This means that there is no static type-safety inherent in user-defined, non-generic, custom interfaces.
Consider the following example of static type safety in a user-defined, custom interface for non-distributed code:
//ITrain is a custom, non-generic interface
//ITrain::GetSpeed( ) returns a variable of a type double
Train*pTrain;
long=pTrain->GetSpeed( );//This will generate a compiler warning GetSpeed( ) method is returning data of type double. However, the returned value is being assigned to variable of type long. This will produce a compilation message.
CORBA uses generic interfaces, which means that similar mistakes will not be detected at the compilation-time but only at run-time. For example, consider the following code:                CORBA::any aVal;        //this is speed taken from an event channel of a variable type double long speed;        if (!(aVal>=speed))//This will compile without warningIn this case GetSpeed( ) method returns a value of type any which is being casted to type long. It will not produce a compilation message and the program will compile just fine. But at run-time, the execution of the above fragment will produce a run-time error. There is no way to detect this problem at the compilation-time. In other words, a static type safety concept requires the programmer or the developer to use known static types rather than dynamic variant types (CORBA::any). If these mismatch problems can be detected at compilation-time, it will save a great deal of testing time and effort.        